﻿#pragma once

#include "CoreMinimal.h"
#include "DepthStencilBuffer.h"
#include "Fix32.h"
#include "FrameBuffer.h"
#include "SoftRendererShader.h"

class UDepthStencilBuffer;
struct FRenderObjectMaterial;

/**
 * 传统基于扫描线的CPU三角形光栅化相关算法
 * 像素计算量少，但是逻辑相对复杂，不合适并行化，适合CPU计算
 */
class FRasterizationCPU
{
protected:
	/**
	 * 梯形的边结构信息
	 */
	struct FEdge
	{
		// 边的开始顶点
		FVertexToPixelInterpolants Start;

		// 边的结束顶点
		FVertexToPixelInterpolants End;
	};
	
	/**
	 * 梯形结构信息
	 */
	struct FTrapezoid
	{
		// 梯形顶部的Y坐标
		float Top;

		// 梯形底部的Y坐标
		float Bottom;

		// 梯形的左边
		FEdge LeftEdge;

		// 梯形的右边
		FEdge RightEdge;
	};

	/**
	 * 将三角形分割成0-2个梯形结构
	 */
	static void TrapezoidTriangle(TArray<FTrapezoid, TInlineAllocator<2>>& TrapezoidList, const FVertexToPixelInterpolants* V1, const FVertexToPixelInterpolants* V2, const FVertexToPixelInterpolants* V3);

	/**
	 * 获取当前扫描线和梯形左右两条边相交的插值顶点信息
	 */
	static void ScanlineVertexInterp(FVertexToPixelInterpolants& LeftScanlineVertex, FVertexToPixelInterpolants& RightScanlineVertex, const FTrapezoid& Trapezoid, float Y);

	/**
	 * 扫描线结构信息
	 */
	struct FScanline
	{
		// 扫描线的像素X坐标
		int32 X;

		// 扫描线的像素Y坐标
		int32 Y;

		// 扫描线的像素宽度
		int32 W;

		// 当前的插值顶点信息
		FVertexToPixelInterpolants Vertex;

		// 插值顶点的步近信息
		FVertexToPixelInterpolants Step;
	};
	
	/**
	 * 根据左右两边的端点，初始化计算出扫描线的起点和步长
	 */
	static FRasterizationCPU::FScanline InitScanline(const FVertexToPixelInterpolants& LeftScanlineVertex, const FVertexToPixelInterpolants& RightScanlineVertex, float Y);

	/**
	 * 填充扫描线像素
	 */
	static void FillScanline(FScanline& Scanline, UFrameBuffer* FrameBuffer);
	
	/**
	 * 填充梯形结构包围的像素
	 */
	static void FillTrapezoid(const FTrapezoid& Trapezoid, UFrameBuffer* FrameBuffer);
	
public:
	/***
	 * 光栅化三角形
	 */
    static void RasterizeTriangle(USoftRenderer* SoftRenderer, const FVertexToPixelInterpolants& V1, const FVertexToPixelInterpolants& V2, const FVertexToPixelInterpolants& V3);
	
};

/**
 * 基于半空间(half-space)光栅化算法的三角形光栅化
 * 算法简单，像素计算量较大，适合并行，也是现代GPU的光栅化方法
 */
class FRasterizationGPU
{
protected:
	/**
	 * 计算边界函数
	 */
	FORCEINLINE static FFix32 EdgeFunction(const FVector2Fix32& Edge0, const FVector2Fix32& Edge1);

	FORCEINLINE static float EdgeFunction(const FVector2D& Edge0, const FVector2D& Edge1);
	
public:
	/**
	 * 光栅化三角形
	 */
	static void RasterizeTriangle(USoftRenderer* SoftRenderer, const FVertexToPixelInterpolants* V1, const FVertexToPixelInterpolants* V2,
		const FVertexToPixelInterpolants* V3, USoftRendererShader* PixelShader, const FRenderObjectMaterial& Material);

	/**
	 * 深度测试
	 */
	static bool DepthTest(ESoftRendererDepthBufferType DepthBufferType, const FVertexToPixelInterpolants& Vertex, const int32 X, const int32 Y, const UDepthStencilBuffer* DepthStencilBuffer, const FRenderObjectMaterial& Material, float& ZDepth);
};
